package com.carb.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.carb.constant.MessageConstant;
import com.carb.context.UserContext;
import com.carb.dto.CarAddDTO;
import com.carb.dto.CarPageQueryDTO;
import com.carb.dto.CarUpdateDTO;
import com.carb.entity.Car;
import com.carb.entity.Member;
import com.carb.enums.CommonDeleted;
import com.carb.enums.UserRole;
import com.carb.exception.EntityNotFoundException;
import com.carb.mapper.CarMapper;
import com.carb.mapper.MemberMapper;
import com.carb.mapper.UserMapper;
import com.carb.query.PageQueryUtils;
import com.carb.result.PageResult;
import com.carb.service.ICarService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.carb.utils.RegexUtils;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 车辆管理 服务实现类
 * </p>
 *
 * @author XuChaoyang
 * @since 2025-01-18
 */
@Service
public class CarServiceImpl extends ServiceImpl<CarMapper, Car> implements ICarService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private MemberMapper memberMapper;

    /**
     * 新增车辆
     * @param carAddDTO 新增车辆信息
     */
    @Override
    @Transactional
    public void addCar(CarAddDTO carAddDTO) {
        // 1、正则校验
        // 车牌号
        String plateNumber = carAddDTO.getPlateNumber();
        RegexUtils.checkPlateNumber(plateNumber);

        // 2、检查车辆车牌号是否已存在且逻辑删除（已删除）
        Car isCarExist = this.getOne(Wrappers.lambdaQuery(Car.class)
                .eq(Car::getPlateNumber, plateNumber)
                .eq(Car::getDeleted, CommonDeleted.DELETED));
        if (isCarExist != null) {
            // 车辆id
            Long carId = isCarExist.getId();
            // 更新车辆逻辑删除为未删除
            BeanUtils.copyProperties(carAddDTO, isCarExist);
            isCarExist.setDeleted(CommonDeleted.NOT_DELETED)
                    .setUpdateTime(LocalDateTime.now())
                    .setLastServiceTime(null);
            this.update(isCarExist, Wrappers.lambdaUpdate(Car.class)
                    .eq(Car::getId, carId));
            // 跳过新增逻辑
            return;
        }

        // 3、检查会员是否存在且未删除
        Long count = memberMapper.selectCount(Wrappers.lambdaQuery(Member.class)
                .eq(Member::getId, carAddDTO.getMemberId())
                .eq(Member::getDeleted, CommonDeleted.NOT_DELETED));
        if (count == 0) {
            throw new EntityNotFoundException(MessageConstant.MEMBER_ACCOUNT_NOT_FOUND);
        }

        // 4、对象属性拷贝
        Car car = new Car();
        BeanUtils.copyProperties(carAddDTO, car);

        // 5、新增车辆
        this.save(car);
    }

    /**
     * 车辆分页查询
     * @param carPageQueryDTO 查询条件
     * @return 车辆分页结果
     */
    @Override
    public PageResult<Car> pageQuery(CarPageQueryDTO carPageQueryDTO) {
        // 1、获取查询属性
        // 1.1、分页属性
        Long pageNum = PageQueryUtils.checkPageNum(carPageQueryDTO.getPageNum());
        Long pageSize = PageQueryUtils.checkPageSize(carPageQueryDTO.getPageSize());
        String orderBy = carPageQueryDTO.getOrderBy();
        Boolean isAsc = carPageQueryDTO.getIsAsc();
        // 1.2、查询属性
        Long memberId = carPageQueryDTO.getMemberId();
        String name = carPageQueryDTO.getName();
        String plateNumber = carPageQueryDTO.getPlateNumber();
        String brand = carPageQueryDTO.getBrand();
        String model = carPageQueryDTO.getModel();

        // 2、构建条件
        // 2.1、分页条件
        Page<Car> page = Page.of(pageNum, pageSize);
        // 2.2、排序条件
        PageQueryUtils.applySorting(page, orderBy, isAsc);
        // 2.3、空结果
        PageResult<Car> emptyPageResult = new PageResult<>(page.getTotal(), page.getPages(), Collections.emptyList());

        // 3、获取会员id集合
        List<Long> memberIdList;
        if (memberId != null) {
            // 如果传入了会员id，则无需查询会员姓名
            memberIdList = List.of(memberId);
        } else {
            // 3.1、根据会员姓名查询会员的用户id
            List<Long> memberUserIdList = userMapper.getUserIdsByName(name, UserRole.MEMBER);
            if (memberUserIdList.isEmpty()) return emptyPageResult;
            // 3.2、根据会员的用户id查询会员id
            memberIdList = memberMapper.getMemberIdsByUserIds(memberUserIdList);
            if (memberIdList.isEmpty()) return emptyPageResult;
        }


        // 4、车辆表查询（车牌号（非空）、车辆品牌（非空）、车辆型号（非空）、逻辑删除（未删除））
        Page<Car> carPage = this.page(page, Wrappers.lambdaQuery(Car.class)
                .in(Car::getMemberId, memberIdList)
                .like(plateNumber != null, Car::getPlateNumber, plateNumber)
                .like(brand != null, Car::getBrand, brand)
                .like(model != null, Car::getModel, model)
                .eq(Car::getDeleted, CommonDeleted.NOT_DELETED));

        // 5、返回封装结果
        return new PageResult<>(carPage.getTotal(), carPage.getPages(), carPage.getRecords());
    }

    /**
     * 根据车辆id查询车辆信息
     * @param id 车辆id
     * @return 查询结果
     */
    @Override
    public Car getCarById(Long id) {
        // 1、检查车辆是否存在，并返回
        return checkCarExist(id);
    }

    /**
     * 修改车辆信息
     * @param carUpdateDTO 修改的车辆信息
     */
    @Override
    @Transactional
    public void updateCar(CarUpdateDTO carUpdateDTO) {
        // 1、检查车辆是否存在
        Long carId = carUpdateDTO.getId();
        Car car = checkCarExist(carId);

        // 2、检查会员是否存在且未删除
        Long count = memberMapper.selectCount(Wrappers.lambdaQuery(Member.class)
                .eq(Member::getId, carUpdateDTO.getMemberId())
                .eq(Member::getDeleted, CommonDeleted.NOT_DELETED));
        if (count == 0) {
            throw new EntityNotFoundException(MessageConstant.MEMBER_ACCOUNT_NOT_FOUND);
        }

        // 3、车辆更新信息（车牌号需要进行正则校验）
        RegexUtils.checkPlateNumber(carUpdateDTO.getPlateNumber());

        // 4、车辆更新
        BeanUtils.copyProperties(carUpdateDTO, car);
        car.setMemberId(carUpdateDTO.getMemberId()).setUpdateTime(LocalDateTime.now());
        this.update(car, Wrappers.lambdaUpdate(Car.class)
                .eq(Car::getId, carId));
    }

    /**
     * 删除车辆（逻辑删除）
     * @param id 车辆id
     */
    @Override
    @Transactional
    public void deleteCar(Long id) {
        // 1、检查车辆是否存在
        checkCarExist(id);

        // 2、更新车辆（逻辑删除）
        this.update(new Car(), Wrappers.lambdaUpdate(Car.class)
                .eq(Car::getId, id)
                .set(Car::getDeleted, CommonDeleted.DELETED));
    }

    /**
     * 新增当前登录会员车辆
     * @param carAddDTO 新增车辆信息
     */
    @Override
    @Transactional
    public void addCurrentMemberCar(CarAddDTO carAddDTO) {
        // 1、获取当前登录会员id
        Long userId = UserContext.getUserId();
        Long memberId = memberMapper.getMemberIdsByUserIds(List.of(userId)).getFirst();
        carAddDTO.setMemberId(memberId);

        // 2、新增车辆
        this.addCar(carAddDTO);
    }

    /**
     * 查询当前登录会员所有车辆
     * @return 车辆列表
     */
    @Override
    public List<Car> listMemberCar() {
        // 1、获取当前登录会员id
        Long userId = UserContext.getUserId();
        Long memberId = memberMapper.getMemberIdsByUserIds(List.of(userId)).getFirst();

        // 2、查询车辆
        return this.list(Wrappers.lambdaQuery(Car.class)
                .eq(Car::getMemberId, memberId)
                .eq(Car::getDeleted, CommonDeleted.NOT_DELETED)
                .orderByDesc(Car::getUpdateTime));
    }

    /**
     * 修改当前登录会员车辆信息
     * @param carUpdateDTO 修改的车辆信息
     */
    @Override
    @Transactional
    public void updateCurrentMemberCar(CarUpdateDTO carUpdateDTO) {
        // 1、获取当前登录会员id
        Long userId = UserContext.getUserId();
        Long memberId = memberMapper.getMemberIdsByUserIds(List.of(userId)).getFirst();
        carUpdateDTO.setMemberId(memberId);

        // 2、修改车辆信息
        this.updateCar(carUpdateDTO);
    }

    /**
     * 删除当前登录会员车辆（逻辑删除）
     * @param id 车辆id
     */
    @Override
    @Transactional
    public void deleteCurrentMemberCar(Long id) {
        // 1、获取当前登录会员id
        Long userId = UserContext.getUserId();
        Long memberId = memberMapper.getMemberIdsByUserIds(List.of(userId)).getFirst();

        // 2、检查车辆是否存在
        checkCarExist(id);

        // 3、更新车辆（逻辑删除）
        this.update(new Car(), Wrappers.lambdaUpdate(Car.class)
                .eq(Car::getId, id)
                .eq(Car::getMemberId, memberId)
                .set(Car::getDeleted, CommonDeleted.DELETED));
    }

    /**
     * 检查车辆是否存在
     * @param carId 车辆id
     * @return 车辆对象
     */
    private Car checkCarExist(Long carId) {
        Car car = this.getOne(Wrappers.lambdaQuery(Car.class)
                .eq(Car::getId, carId)
                .eq(Car::getDeleted, CommonDeleted.NOT_DELETED));
        if (car == null) {
            // 车辆不存在，抛出异常
            throw new EntityNotFoundException(MessageConstant.CAR_NOT_FOUND);
        }
        return car;
    }

}
